#pragma once

class CGdiPlusBitmap
{
public:
    Gdiplus::Bitmap* m_pBitmap;

public:
    CGdiPlusBitmap()
    {
        m_pBitmap = NULL;
    }
    CGdiPlusBitmap(LPCWSTR pFile)
    {
        m_pBitmap = NULL;
        Load(pFile);
    }
    virtual ~CGdiPlusBitmap()
    {
        Empty();
    }

    void Empty()
    {
        delete m_pBitmap;
        m_pBitmap = NULL;
    }

    bool Load(LPCWSTR pFile)
    {
        Empty();
        m_pBitmap = Gdiplus::Bitmap::FromFile(pFile);
        return m_pBitmap->GetLastStatus() == Gdiplus::Ok;
    }

    operator Gdiplus::Bitmap*() const
    {
        return m_pBitmap;
    }
};


class GResource : public CGdiPlusBitmap
{
protected:
    HGLOBAL m_hBuffer;

public:
    GResource()
    {
        m_hBuffer = NULL;
    }
    GResource(LPCTSTR pName, LPCTSTR pType = RT_RCDATA, HMODULE hInst = NULL)
    {
        m_hBuffer = NULL;
        Load(pName, pType, hInst);
    }
    GResource(UINT id, LPCTSTR pType = RT_RCDATA, HMODULE hInst = NULL)
    {
        m_hBuffer = NULL;
        Load(id, pType, hInst);
    }
    GResource(UINT id, UINT type, HMODULE hInst = NULL)
    {
        m_hBuffer = NULL;
        Load(id, type, hInst);
    }
    virtual ~GResource()
    {
        Empty();
    }

    void Empty();

    bool Load(LPCTSTR pName, LPCTSTR pType = RT_RCDATA, HMODULE hInst = NULL);
    bool Load(UINT id, LPCTSTR pType = RT_RCDATA, HMODULE hInst = NULL)
    {
        return Load(MAKEINTRESOURCE(id), pType, hInst);
    }
    bool Load(UINT id, UINT type, HMODULE hInst = NULL)
    {
        return Load(MAKEINTRESOURCE(id), MAKEINTRESOURCE(type), hInst);
    }
};

inline
void GResource::Empty()
{
    CGdiPlusBitmap::Empty();

    if (m_hBuffer) {
        ::GlobalUnlock(m_hBuffer);
        ::GlobalFree(m_hBuffer);
        m_hBuffer = NULL;
    }
}

inline
bool GResource::Load(LPCTSTR pName, LPCTSTR pType, HMODULE hInst)
{
    Empty();
    HRSRC hResource = ::FindResource(hInst, pName, pType);

    if (!hResource)
        return false;

    DWORD imageSize = ::SizeofResource(hInst, hResource);

    if (!imageSize)
        return false;

    const void* pResourceData = ::LockResource(::LoadResource(hInst, hResource));

    if (!pResourceData)
        return false;

    m_hBuffer  = ::GlobalAlloc(GMEM_MOVEABLE, imageSize);

    if (m_hBuffer) {
        void* pBuffer = ::GlobalLock(m_hBuffer);

        if (pBuffer) {
            CopyMemory(pBuffer, pResourceData, imageSize);
            IStream* pStream = NULL;

            if (::CreateStreamOnHGlobal(m_hBuffer, FALSE, &pStream) == S_OK) {
                m_pBitmap = Gdiplus::Bitmap::FromStream(pStream);
                pStream->Release();

                if (m_pBitmap) {
                    if (m_pBitmap->GetLastStatus() == Gdiplus::Ok)
                        return true;

                    delete m_pBitmap;
                    m_pBitmap = NULL;
                }
            }

            ::GlobalUnlock(m_hBuffer);
        }

        ::GlobalFree(m_hBuffer);
        m_hBuffer = NULL;
    }

    return false;
}
